using System;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Printing;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Collections.Generic;
using Wicresoft.IDE.Designer;
using Wicresoft.IDE.Loader;
using UmcProvider;
using System.Xml;

namespace Wicresoft.IDE.Shell
{
    /// <summary>
    /// This is the Wicresoft.IDE.Core.Shell that has the Toolbox, PropertyGrid, hosts Designers, etc.
    /// </summary>
    public partial class MainShell : Wicresoft.IDE.Components.Controls.RichForm
    {
        private int _umcControlCount = 0;
        private HostSurfaceManager _hostSurfaceManager = null;
        private ToolTip tabControlToolTip = null;

        //change ctor , get path arg and open the file(change by P_Chou_cp)
        public MainShell(string[] arg)
        {
            InitializeComponent();
            CustomInitialize();

            //get path arg and open the file
            if (0 != arg.Length)
            {
                var fileName = arg[0];
                if (File.Exists(fileName))
                {
                    CreateTabView(fileName);

                    try
                    {
                        string code = codeView.Text;
                        XmlDocument xml = new XmlDocument();
                        xml.LoadXml(code);
                        HostControl hc = CurrentDocumentsHostControl;
                        new CodeDomLoader().DeSerialize(
                           hc.DesignerHost,
                           xml);

                        codeView.Text = code;
                    }
                    catch
                    {

                    }
                }
                else
                    MessageBox.Show("Unknown file " + fileName);
            }
        }

        /// <summary>
        /// Adds custom services to the HostManager like Toolbox, PropertyGrid.
        /// </summary>
        private void CustomInitialize()
        {
            this.Size = new Size(950, 635);
            var startPage = new StartPage { Name = "startPage", Dock = DockStyle.Fill };
            hostPanel.Controls.Add(startPage);
            hostPanel.Controls.Find("designSplitContainer", false)[0].Hide();
            codeView.Font = base.CreateGBFont();

            startPage.RecentFileOpened += new StartPage.OpenRecentFileHandler(StartPage_RecentFileOpened);

            _hostSurfaceManager = new HostSurfaceManager();
            _hostSurfaceManager.AddService(typeof(IToolboxService), this.Toolbox);
            _hostSurfaceManager.AddService(typeof(System.Windows.Forms.PropertyGrid), this.propertyGrid);

            this.tabControl.SelectedIndexChanged += new EventHandler(tabControl_SelectedIndexChanged);
        }

        void StartPage_RecentFileOpened(object sender, RecentFileEventArgs e)
        {
            CreateTabView(e.FileName);
        }

        private HostControl CurrentDocumentsHostControl
        {
            get
            {
                if (this.tabControl.TabPages.Count == 0)
                {
                    return null;
                }
                else
                {
                    return (HostControl)this.tabControl.SelectedTab.Controls[0];
                }
            }
        }

        private bool DisposeLoader()
        {
            UMCHostLoader currentLoader = (UMCHostLoader)CurrentDocumentsHostControl.HostSurface.Loader;
            DialogResult result = currentLoader.PromptDispose();
            if (result == DialogResult.Yes)
            {
                if (!currentLoader.IsUnsaved)
                {
                    currentLoader.Dispose();
                    return true;
                }
                return false;
            }
            else if (result == DialogResult.No)
            {
                currentLoader.Dispose();
                return true;
            }
            else if (result == DialogResult.Cancel)
            {
                return false;
            }
            return true;
        }

        #region UI Event

        #region TabControl Event

        /// <summary>
        /// Trigger when selected tab is changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (CurrentDocumentsHostControl != null)
            {
                this.codeView.Text = ((UMCHostLoader)CurrentDocumentsHostControl.HostSurface.Loader).GetCode();
            }
        }

        /// <summary>
        /// Draw close button on the tab control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControl_DrawItem(object sender, DrawItemEventArgs e)
        {
            Rectangle tabRect = this.tabControl.GetTabRect(e.Index);
            e.Graphics.DrawString(this.tabControl.TabPages[e.Index].Text,
                this.Font, SystemBrushes.ControlText, tabRect.X + 2, tabRect.Y + 2);
            using (Pen pen = new Pen(Color.Black))
            {
                tabRect.Offset(tabRect.Width - (12 + 3), 2);
                tabRect.Width = 12;
                tabRect.Height = 12;
                e.Graphics.DrawRectangle(pen, tabRect);
            }
            Color color = e.State == DrawItemState.Selected ? Color.DarkRed : Color.DarkGray;
            using (Brush brush = new SolidBrush(color))
            {
                e.Graphics.FillRectangle(brush, tabRect);
            }
            using (Pen pen = new Pen(Color.White))
            {
                Point p1 = new Point(tabRect.X + 3, tabRect.Y + 3);
                Point p2 = new Point(tabRect.X + tabRect.Width - 3, tabRect.Y + tabRect.Height - 3);
                e.Graphics.DrawLine(pen, p1, p2);

                Point p3 = new Point(tabRect.X + 3, tabRect.Y + tabRect.Height - 3);
                Point p4 = new Point(tabRect.X + tabRect.Width - 3, tabRect.Y + 3);
                e.Graphics.DrawLine(pen, p3, p4);
            }
            e.Graphics.Dispose();

        }

        /// <summary>
        /// Trigger when mouse down on the customized close button on the tab
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                int x = e.X, y = e.Y;
                Rectangle tabRect = this.tabControl.GetTabRect(this.tabControl.SelectedIndex);
                tabRect.Offset(tabRect.Width - (12 + 3), 2);
                tabRect.Width = 12;
                tabRect.Height = 12;
                bool isClose = x > tabRect.X && x < tabRect.Right
                 && y > tabRect.Y && y < tabRect.Bottom;

                if (isClose == true)
                {
                    if (DisposeLoader())
                    {
                        this.tabControl.TabPages.Remove(this.tabControl.SelectedTab);
                    }
                }
                if (this.tabControl.TabPages.Count == 0)
                {
                    this.tabControl.Visible = false;
                    this.codeView.Visible = false;
                    this.saveAsMenuItem.Enabled = false;
                    this.saveMenuItem.Enabled = false;
                    this.saveAllMenuItem.Enabled = false;
                }
            }
        }

        void tabControl_MouseLeave(object sender, EventArgs e)
        {
            if (tabControlToolTip != null)
            {
                tabControlToolTip.Dispose();
            }
        }

        void tabControl_MouseEnter(object sender, EventArgs e)
        {
            int x = MousePosition.X;
            int y = MousePosition.Y;
            Rectangle rect = this.tabControl.GetTabRect(this.tabControl.SelectedIndex);
            rect = this.tabControl.RectangleToScreen(rect);
            if (rect.Contains(x, y))
            {
                tabControlToolTip = new ToolTip();
                string content = ((UMCHostLoader)CurrentDocumentsHostControl.HostSurface.Loader).FileName;
                tabControlToolTip.IsBalloon = false;
                tabControlToolTip.Show(content, this.tabControl);
            }
        }

        #endregion

        #region MenuItem Event

        /// <summary>
        /// Save file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void saveMenuItem_Click(object sender, System.EventArgs e)
        {
            HostControl currentHostControl = CurrentDocumentsHostControl;
            if ((LoaderType)this.tabControl.SelectedTab.Tag == LoaderType.UMCDesignerLoader)
            {
                UMCHostLoader umcHostLoader = (UMCHostLoader)currentHostControl.HostSurface.Loader;
                umcHostLoader.Save();
                if (!string.IsNullOrEmpty(umcHostLoader.FileName))
                {
                    this.tabControl.SelectedTab.Text = umcHostLoader.FileName.Substring(umcHostLoader.FileName.LastIndexOf(@"\") + 1);
                }
                this.StatusBar.Text = Resource.FileSavedStatusString;
            }
        }

        /// <summary>
        /// Save file. Force to prompt save file dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void saveAsMenuItem_Click(object sender, System.EventArgs e)
        {
            HostControl currentHostControl = CurrentDocumentsHostControl;
            if ((LoaderType)this.tabControl.SelectedTab.Tag == LoaderType.UMCDesignerLoader)
            {
                UMCHostLoader umcHostLoader = (UMCHostLoader)currentHostControl.HostSurface.Loader;
                umcHostLoader.Save(true);
                if (!string.IsNullOrEmpty(umcHostLoader.FileName))
                {
                    this.tabControl.SelectedTab.Text = umcHostLoader.FileName.Substring(umcHostLoader.FileName.LastIndexOf(@"\") + 1);
                }
                this.StatusBar.Text = Resource.FileSavedStatusString;
            }
        }

        /// <summary>
        /// Close the IDE
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitMenuItem_Click(object sender, System.EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// To Do
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void optionMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Options can be implemented here");
        }

        /// <summary>
        /// Show the About dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void aboutMenuItem_Click(object sender, EventArgs e)
        {
            using (AboutIDE aboutfrm = new AboutIDE())
            {
                aboutfrm.ShowDialog();
            }
        }

        /// <summary>
        /// Open a saved file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void openMenuItem_Click(object sender, System.EventArgs e)
        {
            try
            {
                string fileName = null;

                // Open File Dialog
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.DefaultExt = Resource.UMCFileExtention;
                dlg.Filter = Resource.UMCFileFilter;
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    fileName = dlg.FileName;
                }
                else
                {
                    return;
                }

                if (fileName.EndsWith(Resource.UMCFileExtention))
                {
                    CreateTabView(fileName);
                    RecentFileUtil.AddRecentFile(fileName);
                }
            }
            catch
            {
                MessageBox.Show("Error in creating new host", "Wicresoft.IDE.Shell Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Click to new a UMC file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void newMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                using (Form p = new NewForm())
                {
                    p.ShowDialog();
                    if (p.DialogResult == DialogResult.OK)
                        CreateTabView(null);
                }
            }
            catch
            {
                MessageBox.Show("Error in creating new host", "Wicresoft.IDE.Shell Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Click to new a UMC file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void saveAllMenuItem_Click(object sender, EventArgs e)
        {
            SaveAllFiles();
        }

        #endregion

        private void MainShell_updateCodeView(string code)
        {
            if (codeView.Focused)
                return;
            this.codeView.Text = code;
            if (!this.tabControl.SelectedTab.Text.EndsWith(Resource.UnSavedMark))
            {
                this.tabControl.SelectedTab.Text += Resource.UnSavedMark;
            }
        }

        private void printFunction(object sender, PrintPageEventArgs ev)
        {
            string text = "";
            text = codeView.Text;
            ev.Graphics.DrawString(text, codeView.Font, Brushes.Black, 10, 10);
        }

        private void PrintMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                PrintDocument pd = new PrintDocument();
                pd.PrintController = new StandardPrintController();
                pd.PrintPage += new PrintPageEventHandler(printFunction);
                printDialog.Document = pd;
                DialogResult result = printDialog.ShowDialog();
                if (result == DialogResult.OK)
                    pd.Print();
            }
            catch
            {
                MessageBox.Show("Error in print", "Wicresoft.IDE.Shell Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CutMenuItem_Click(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(codeView.Text);
            codeView.Text = "";
        }

        private void CopyMenuItem_Click(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(codeView.Text);
        }

        private void PasteMenuItem_Click(object sender, EventArgs e)
        {
            IDataObject iData = Clipboard.GetDataObject();
            if (iData.GetDataPresent(DataFormats.Text))
                codeView.Text = (string)iData.GetData(DataFormats.Text);
        }

        #endregion

        private void CodeView_TextChanged(object sender, EventArgs e)
        {
            if (!codeView.Focused)
                return;

            this.Cursor = Cursors.WaitCursor;

            try
            {
                string code = codeView.Text;
                XmlDocument xml = new XmlDocument();
                xml.LoadXml(code);
                HostControl hc = CurrentDocumentsHostControl;
                new CodeDomLoader().DeSerialize(
                   hc.DesignerHost,
                   xml);

            }
            catch
            {

            }

            this.Cursor = Cursors.Default;
        }

        private void CreateTabView(string fileFullName)
        {
            hostPanel.Controls.Find("startPage", false)[0].Hide();
            hostPanel.Controls.Find("designSplitContainer", false)[0].Show();
            printToolStripButton.Enabled = true;

            IDataObject iData = Clipboard.GetDataObject();
            if (iData.GetDataPresent(DataFormats.Text))
                pasteToolStripButton.Enabled = true;

            _umcControlCount++;
            HostControl hc = _hostSurfaceManager.GetNewHost(typeof(UmcProvider.UmcHost), LoaderType.UMCDesignerLoader);
            string tabText = fileFullName;
            if (string.IsNullOrEmpty(tabText))
            {
                tabText = string.Format(Resource.NewUMCFileTitle, _umcControlCount.ToString(), Resource.UnSavedMark);
            }
            else
            {
                tabText = fileFullName.Substring(fileFullName.LastIndexOf(@"\") + 1);
            }
            TabPage tabpage = new TabPage(tabText);
            tabpage.Tag = LoaderType.UMCDesignerLoader;

            hc.Dock = DockStyle.Fill;
            hc.Parent = tabpage;
            this.Toolbox.DesignerHost = hc.DesignerHost;
            this.tabControl.TabPages.Add(tabpage);
            this.tabControl.SelectedIndex = this.tabControl.TabPages.Count - 1;
            this.tabControl.Visible = true;
            this.saveAsMenuItem.Enabled = true;
            this.saveMenuItem.Enabled = true;
            this.saveAllMenuItem.Enabled = true;
            this.codeView.Visible = true;

            UMCHostLoader umcHostLoader = (UMCHostLoader)hc.HostSurface.Loader;
            umcHostLoader.updateCodeView += new UMCHostLoader.UpdateCodeView(MainShell_updateCodeView);

            if (string.IsNullOrEmpty(fileFullName))
            {
                this.codeView.Text = umcHostLoader.GetCode();
                umcHostLoader.IsUnsaved = true;
            }
            else
            {
                this.codeView.Focus();
                using (StreamReader sr = new StreamReader(fileFullName))
                {
                    string code = string.Empty;
                    code = sr.ReadToEnd();
                    this.codeView.Text = code;
                }
                umcHostLoader.IsUnsaved = false;
                umcHostLoader.FileName = fileFullName;
            }
            umcHostLoader.IsDirty = false;
            this.StatusBar.Text = Resource.StatusReady;

            if (codeView.Text != "")
            {
                cutToolStripButton.Enabled = true;
                copyToolStripButton.Enabled = true;
            }
        }

        private bool DoesAllFilesSaved()
        {
            bool ret = true;
            for (int i = 0; i < this.tabControl.TabCount; i++)
            {
                HostControl hc = (HostControl)this.tabControl.TabPages[i].Controls[0];
                if (((UMCHostLoader)hc.HostSurface.Loader).IsUnsaved
                    || ((UMCHostLoader)hc.HostSurface.Loader).IsDirty)
                {
                    ret = false;
                    break;
                }
            }
            return ret;
        }

        private void SaveAllFiles()
        {
            for (int i = 0; i < this.tabControl.TabCount; i++)
            {
                HostControl hc = (HostControl)this.tabControl.TabPages[i].Controls[0];
                ((UMCHostLoader)hc.HostSurface.Loader).Save();
                string title = ((UMCHostLoader)hc.HostSurface.Loader).FileName;
                if (!string.IsNullOrEmpty(title))
                {
                    this.tabControl.TabPages[i].Text = title.Substring(title.LastIndexOf(@"\") + 1);
                }
            }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Delete)
            {
                IMenuCommandService ims = this.CurrentDocumentsHostControl.HostSurface.GetService(typeof(IMenuCommandService)) as IMenuCommandService;
                ims.GlobalInvoke(StandardCommands.Delete);
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void MainShell_Load(object sender, EventArgs e)
        {
        }

        private void newToolStripButton_Click(object sender, EventArgs e)
        {
            newMenuItem_Click(sender, e);
        }

        private void helpToolStripButton_Click(object sender, EventArgs e)
        {
            aboutMenuItem_Click(sender, e);
        }

        private void openToolStripButton_Click(object sender, EventArgs e)
        {
            openMenuItem_Click(sender, e);
        }

        private void saveToolStripButton_Click(object sender, EventArgs e)
        {
            saveMenuItem_Click(sender, e);
        }

        private void printToolStripButton_Click(object sender, EventArgs e)
        {
            PrintMenuItem_Click(sender, e);
        }

        private void cutToolStripButton_Click(object sender, EventArgs e)
        {
            CutMenuItem_Click(sender, e);
        }

        private void pasteToolStripButton_Click(object sender, EventArgs e)
        {
            PasteMenuItem_Click(sender, e);
        }

        private void copyToolStripButton_Click(object sender, EventArgs e)
        {
            CopyMenuItem_Click(sender, e);
        }

        private void closeAWMenuItem_Click(object sender, EventArgs e)
        {

        }
    }
}
